package com.tanhua.dubbo.api;

import com.tanhua.domain.mongo.Comment;
import com.tanhua.domain.mongo.Publish;
import com.tanhua.domain.mongo.Video;
import com.tanhua.domain.vo.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.util.List;

/**
 * @author
 * @date 2021/01/25
 */
@Slf4j
@Service
public class CommentApiImpl implements CommentApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public long save(Comment comment) {
        //补全数据
        comment.setId(ObjectId.get());
        comment.setCreated(System.currentTimeMillis());
        //保存评论
        mongoTemplate.save(comment);
        //更新动态评论数量+1，得到更新后的动态publish
        Query query = new Query(Criteria.where("id").is(comment.getPublishId()));
        Update update = new Update().inc(getColName(comment.getCommentType()), 1);
        //设置选项
        FindAndModifyOptions options = new FindAndModifyOptions();
        //返回最新的
        options.returnNew(true);
        Publish publish = mongoTemplate.findAndModify(query, update, options, Publish.class);
        //返回最新的计数
        return getCountByCommentType(publish,comment.getCommentType());
    }


    @Override
    public long remove(Comment comment) {
        //删除评论记录
        Criteria criteria = Criteria.where("publishId").is(comment.getPublishId())
                .and("userId").is(comment.getUserId())
                .and("commentType").is(comment.getCommentType())
                .and("pubType").is(comment.getPublishId());
        Query query = new Query(criteria);
        mongoTemplate.remove(query, Comment.class);
        //更新动态评论数量-1
        query = new Query(Criteria.where("id").is(comment.getPublishId()));
        Update update = new Update().inc(getColName(comment.getCommentType()), -1);
        //设置选项
        FindAndModifyOptions options = new FindAndModifyOptions();
        //返回最新的
        options.returnNew(true);
        Publish publish = mongoTemplate.findAndModify(query, update, options, Publish.class);
        return getCountByCommentType(publish,comment.getCommentType());
    }

    @Override
    public PageResult<Comment> findComment(String movementId, int page, int pagesize) {
        // 查询条件：publishId动态id， commentType评论类型2（2是评论，1是点赞，3是喜欢）
        Criteria criteria = Criteria.where("publishId").is(new ObjectId(movementId)).and("commentType").is(2);
        //设置排序和分页
        Query query = new Query(criteria)
                .with(Sort.by(Sort.Order.desc("likeCount"), Sort.Order.desc("created")))
                .with(PageRequest.of(page - 1, pagesize));
        //查询
        List<Comment> list = mongoTemplate.find(query, Comment.class);
        long count = mongoTemplate.count(query, Comment.class);
        int pages = (int) Math.ceil(count * 1.0 / pagesize);
        return new PageResult<>((int)count,pagesize,pages,page,list);
    }

    @Override
    public long saveVideo(Comment comment) {
        //补全数据
        comment.setId(ObjectId.get());
        comment.setCreated(System.currentTimeMillis());
        //保存评论
        mongoTemplate.save(comment);
        //更新动态评论数量+1，得到更新后的动态publish
        Query query = new Query(Criteria.where("id").is(comment.getPublishId()));
        Update update = new Update().inc(getColName(comment.getCommentType()), 1);
        //设置选项
        FindAndModifyOptions options = new FindAndModifyOptions();
        //返回最新的
        options.returnNew(true);
        Video video = mongoTemplate.findAndModify(query, update, options, Video.class);
        //返回最新的计数
        return getCountByCommentType(video,comment.getCommentType());
    }

    @Override
    public long removeVideo(Comment comment) {
        //删除评论记录
        Criteria criteria = Criteria.where("publishId").is(comment.getPublishId())
                .and("userId").is(comment.getUserId())
                .and("commentType").is(comment.getCommentType())
                .and("pubType").is(comment.getPublishId());
        Query query = new Query(criteria);
        mongoTemplate.remove(query, Comment.class);
        //更新动态评论数量-1
        query = new Query(Criteria.where("id").is(comment.getPublishId()));
        Update update = new Update().inc(getColName(comment.getCommentType()), -1);
        //设置选项
        FindAndModifyOptions options = new FindAndModifyOptions();
        //返回最新的
        options.returnNew(true);
        Video video = mongoTemplate.findAndModify(query, update, options, Video.class);
        return getCountByCommentType(video,comment.getCommentType());
    }

    @Override
    public PageResult<Comment> findCommentsByUser(Long userId, int commentType, int page, int pagesize) {
        Criteria criteria = Criteria.where("publishUserId").is(userId)
                .and("commentType").is(commentType);
        Query query = new Query(criteria)
                .with(Sort.by(Sort.Order.desc("created")))
                .with(PageRequest.of(page - 1, pagesize));
        List<Comment> commentList = mongoTemplate.find(query, Comment.class);
        long count = mongoTemplate.count(query, Comment.class);
        int pages = (int) Math.ceil(count * 1.0 / pagesize);
        return new PageResult<>((int)count,pagesize,pages,page,commentList);
    }

    /**
     * 根据操作类型，获取要操作的字段名称
     * @param commentType 操作类型。1点赞，2评论，3喜欢
     * @return 操作类型对应的字段名
     */
    private String getColName(Integer commentType){
        if (commentType == 1) {
            return "likeCount";
        }else if (commentType == 2) {
            return "commentCount";
        } else if (commentType == 3) {
            return "loveCount";
        }
        return "";
    }

    /**
     * 根据操作类型，从Publish中获取相应的计数
     * @param publish 动态信息publish
     * @param commentType 操作类型（1点赞，2评论，3喜欢）
     * @return commentType相应的计数
     */
    private long getCountByCommentType(Publish publish, int commentType){
        if (commentType == 1) {
            //点赞了，返回最新点赞数
            return publish.getLikeCount();
        }else if(commentType == 2){
            //评论了，返回最新评论数
            return publish.getCommentCount();
        }else if(commentType == 3){
            //喜欢了，返回最新喜欢数
            return publish.getLoveCount();
        }
        return 0;
    }
    /**
     * 根据操作类型，从video中获取相应的计数
     * @param video 动态信息video
     * @param commentType 操作类型（1点赞，2评论，3喜欢）
     * @return commentType相应的计数
     */
    private long getCountByCommentType(Video video, int commentType){
        if (commentType == 1) {
            //点赞了，返回最新点赞数
            return video.getLikeCount();
        }else if(commentType == 2){
            //评论了，返回最新评论数
            return video.getCommentCount();
        }else if(commentType == 3){
            //喜欢了，返回最新喜欢数
            return video.getLoveCount();
        }
        return 0;
    }
}